#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
@File    ：data_process.py
@IDE     ：PyCharm 
@Author  ：lmy
@Date    ：2024/7/13 12:27 
'''

import re
import json
import pandas as pd
import phonenumbers
from datetime import timedelta, datetime
from feature_set.sms.utils.data_utils import tikenization
from feature_conf.config import GenericConfigConstant
import warnings

warnings.filterwarnings("ignore")


def phone_normalize(phone, country_id):
    """
    :param phone:
    :param country_id: 国家地区代码 ISO标准 .e.g.MX、CL,需大写
    :return:
    """
    phone = re.sub(r'[*\#\-()\n\t \u202A\u202C]+', '', str(phone)).lower()
    phone = phone[:]
    length = len(phone)
    # 清洗+00593964132978该类手机号
    try:
        if phone[0] == '+':
            phone = '+' + phone.replace('+', '').lstrip('0')
            length = len(phone) - 1
        else:
            phone = phone.lstrip('0')
            length = len(phone)
    except Exception:
        pass
    # 初始化
    is_valid, country_code, national_phone = 0, '', phone.lstrip('+')

    # 若手机号长度小于7（最短手机号），则返回
    if length < 7:
        return str(national_phone)

    try:
        if phone.startswith('+'):
            parse_info = phonenumbers.parse(phone)
        else:
            parse_info = phonenumbers.parse(phone, country_id)

        is_valid = 1 if phonenumbers.is_valid_number(parse_info) else 0
        if is_valid:
            national_phone = parse_info.national_number
            return str(national_phone)
    except Exception:
        pass

    return str(national_phone)


def day_diff_classify(day_diff, time_type):
    """
    时间窗口分类
    """
    time_type_hash = {'d1': 1, 'd7': 7, 'd15': 15, 'm1': 30, 'm3': 90, 'm6': 180}
    x = time_type_hash[time_type]
    y = day_diff // x
    return y if y <= 1 else 2


def word_slot_classify(word_len):
    """
    单词长度分类
    """
    if word_len <= 4:
        return 0
    elif word_len < 10:
        return 1
    elif word_len < 15:
        return 2
    elif word_len < 23:
        return 3
    else:
        return 4


def time_trans(time, country_code):
    tz = GenericConfigConstant.COUNTRY_TIME_ZONE[country_code.lower()]
    time_len = len(str(time))
    time_format = "%a %b %d %H:%M:%S GMT%z %Y"
    if time_len == 10:
        format_time = datetime.utcfromtimestamp(int(time)) + timedelta(hours=tz)
    elif time_len == 13:
        format_time = datetime.utcfromtimestamp(int(time) // 1000) + timedelta(hours=tz)
    elif time_len == 34:
        format_time = datetime.strptime(str(time), time_format)
    else:
        format_time = datetime(2099, 12, 31, 23, 59, 59)

    return format_time


def data_processing(data_sources, apply_time, fea_key, country_code, language):
    """
    data_source:传入的json数据
    apply_time:申请时间
    fea_key:需要解析的特征名，e.g. sms_data
    country_code:国家地区代码 ISO标准 .e.g.MX、CL,需大写
    langeuage:语言 e.g.spanish

    """
    columns_lst = ['app_order_id', 'time_day', 'time_diff', 'time_date', 'time', 'type', 'read', 'apply_day', 'body',
                   'body_pre',
                   'word', 'src_phone', 'phone', 'sender', 'is_digit', 'weekday', 'date_period', 'hour', 'week',
                   'month', 'd1od1', 'd7od7', 'd15od15', 'm1om1', 'm3om3', 'm6om6']
    sms_lst = data_sources[fea_key]
    if not sms_lst or sms_lst == []:
        user_sms = pd.DataFrame(columns=columns_lst)
    else:
        user_sms = pd.DataFrame(sms_lst)

    # 过滤掉申请时间之后的短信
    user_sms['time'] = user_sms['time'].apply(lambda x: time_trans(x, country_code))
    user_sms['time'] = pd.to_datetime(user_sms['time'], errors='coerce')
    user_sms = user_sms[user_sms['time'].apply(lambda x: str(x)[:19]) <= str(apply_time)[:19]]

    # 选取每个人的最近3000条短信
    user_sms = user_sms.sort_values(by=['time'], ascending=False)
    user_sms = user_sms.head(3000)
    if user_sms.shape[0] != 0:

        # 时间相关处理
        user_sms['time_day'] = user_sms['time'].dt.strftime("%Y-%m-%d")
        user_sms['apply_day'] = str(apply_time)[:10]
        user_sms['time_diff'] = (pd.to_datetime(user_sms['apply_day']) - pd.to_datetime(user_sms['time_day'])).map(
            lambda x: x.days)
        user_sms['time_diff'] = (user_sms['time_diff'].clip(lower=0)).fillna(999).astype(int)
        user_sms['time_date'] = user_sms['time'].dt.strftime("%Y-%m-%d %H")

        # 对'body'字段进行预处理
        user_sms['body'] = user_sms['body'].apply(lambda x: str(x).lower())  # 将'body'字段中的所有文本转换为小写
        user_sms['body_pre'] = user_sms['body'].apply(
            lambda x: re.sub(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', '', str(x)))  # 去除邮箱
        user_sms['body_pre'] = user_sms['body_pre'].apply(
            lambda x: re.sub(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', '',
                             str(x)))  # 去除URL
        user_sms['body_pre'] = user_sms['body_pre'].apply(lambda x: re.sub(r'[^\w\s]', '', str(x)))  # 去除特殊字符
        user_sms['body_pre'] = user_sms['body_pre'].apply(lambda x: re.sub(r'\d+', '', str(x)))  # 去除数字

        # 分词
        user_sms['word'] = user_sms['body'].apply(lambda x: tikenization(x, language))
        user_sms['word'] = user_sms['word'].apply(lambda x: [re.sub(r'[^\w]', '', str(i)) for i in x])  # 去除特殊字符
        user_sms['word'] = user_sms['word'].apply(lambda x: [re.sub(r'\d+', '', str(i)) for i in x])  # 去除数字
        user_sms['word'] = user_sms['word'].apply(lambda x: [i for i in x if i != ''])  # 去除空字符

        # 清洗手机号
        user_sms['src_phone'] = user_sms['src_phone'].apply(lambda x: str(x))
        user_sms['src_phone'] = user_sms.apply(
            lambda x: x['phone'] if len(x['src_phone']) < len(x['phone']) else x['src_phone'], axis=1)
        user_sms['src_phone_len'] = user_sms['src_phone'].apply(lambda x: len(x))
        user_sms = user_sms[user_sms['src_phone_len'] > 1]
        user_sms['sender'] = user_sms['src_phone'].apply(lambda x: phone_normalize(x, country_code))
        user_sms['is_digit'] = user_sms['sender'].apply(lambda x: 1 if str(x).isdigit() else 0)

        # 提取出日期中的星期信息
        user_sms['weekday'] = user_sms['time'].dt.weekday

        # 创建一个新的'time_period'字段，如果是周一至周五（weekday < 5）则为'weekday'，否则为'weekend'
        user_sms['date_period'] = user_sms['weekday'].apply(lambda x: 'weekday' if x < 5 else 'weekend')

        # 提取hour、week、month信息
        user_sms['hour'] = user_sms['time'].dt.hour
        user_sms['week'] = user_sms['time'].dt.strftime("%Y-%W")
        user_sms['month'] = user_sms['time'].dt.strftime("%Y-%m")

        # 最近多少天的标签
        user_sms['d1od1'] = user_sms['time_diff'].apply(day_diff_classify, time_type='d1')
        user_sms['d7od7'] = user_sms['time_diff'].apply(day_diff_classify, time_type='d7')
        user_sms['d15od15'] = user_sms['time_diff'].apply(day_diff_classify, time_type='d15')
        user_sms['m1om1'] = user_sms['time_diff'].apply(day_diff_classify, time_type='m1')
        user_sms['m3om3'] = user_sms['time_diff'].apply(day_diff_classify, time_type='m3')
        user_sms['m6om6'] = user_sms['time_diff'].apply(day_diff_classify, time_type='m6')

        # 类型统一转换成字符
        user_sms['read'] = user_sms['read'].apply(lambda x: str(x))
        user_sms['type'] = user_sms['type'].apply(lambda x: str(x))
    else:

        user_sms = pd.DataFrame(columns=columns_lst)

    return user_sms
